package com.afeng.util.log;

import java.util.HashMap;
import java.util.Map;
import java.util.Set;

import org.apache.commons.lang3.StringUtils;

/**
 * 
 * @Title       : LogMessage
 * @Description : 日志打印对象封装
 * @Date        : 2017年11月15日
 * @author      : afeng
 */
public class LogMessageUtil implements DltagConstant {
    
    /**
     * 定义日志打印对象中需要线程内透传的threadlocal集合（日志中需要透传的key/value对象集合）
     */
    private static ThreadLocal<Map<String, String>> extElements = new InheritableThreadLocal<Map<String, String>>() {
        @Override
        protected Map<String, String> initialValue() {
            return new HashMap<>();
        };
    };
    
    /**
     * 日志中traceid的key统一约定（请求全链路透传，放到threadlocal对象的map中）
     */
    public static final String TRACE_ID_FLAG = "traceid";
    
    /**
     * 日志中spanid的key统一约定（请求本线程模块透传，放到threadlocal对象的map中）
     */
    public static final String SPAN_ID_FLAG = "spanid";
    
    //代表有业务类型或者具体业务含义的标签
    private String dltag = "";
    
    //本模块的下游模块的spanid，在调用下游模块时，在本模块生成cspanid，并打印，然后透传到下游模块（本模块内不需要透传，只在调用下游模块时打印并透传到下游模块）
    private String cspanId = "";

    /**
     * 定义日志中只需要在本条日志打印的集合
     */
    private Map<String, String> logElements = new HashMap<String, String>();

    public static String getTraceId() {
        return extElements.get().get(TRACE_ID_FLAG);
    }

    public static String getSpanId() {
        return extElements.get().get(SPAN_ID_FLAG);
    }

    public static void setTraceId(String traceId) {
        extElements.get().put(TRACE_ID_FLAG,traceId);
    }

    public static void setSpanId(String spanId) {
        extElements.get().put(SPAN_ID_FLAG,spanId);
    }
    
    public static void addToThreadLocal(String key, String value) {
        if(StringUtils.isBlank(key)) {
            return;
        }
        extElements.get().put(key,value);
    }

    public LogMessageUtil setCspanId(String cspanId) {
        this.cspanId = cspanId;
        return this;
    }

    public LogMessageUtil setDltag(String dltag) {
        this.dltag = dltag;
        return this;
    }

    public LogMessageUtil add(String key, Object value) {
        if(StringUtils.isBlank(key)) {
            return this;
        }
        logElements.put(key,value==null?"":value.toString());
        return this;
    }

    public Map<String, String> getLogElements() {
        return logElements;
    }

    public void setLogElements(Map<String, String> logElements) {
        this.logElements = logElements;
    }

    public String getDltag() {
        if (dltag == null || dltag.equals("")) {
            return DEFAULT_DLTAG;
        }
        return dltag;
    }

    public String getCspanId() {
        return cspanId;
    }

    public static void remove() {
        extElements.remove();
    }

    public String toString() {
        Map<String, String> extElement = extElements.get();
        Set<String> keySet = extElement.keySet();
        
        StringBuffer sb = new StringBuffer();
        sb.append(getDltag());
        for(String key:keySet) {
            sb.append("||");
            sb.append(key);
            sb.append("=");
            sb.append(extElement.get(key));
        }
        sb.append("||cspanid=");
        sb.append(getCspanId());
        
        Set<String> keySet2 = logElements.keySet();
        for(String key:keySet2) {
            sb.append("||");
            sb.append(key);
            sb.append("=");
            sb.append(logElements.get(key));
        }
        return sb.toString();
    }
}
